#ifndef CAFFE_BASE_HPP_
#define CAFFE_BASE_HPP_
#include <string>
#include <memory>
#include <vector>
#include <climits>
#include <cmath>
#include <fstream>  // NOLINT(readability/streams)
#include <iostream>  // NOLINT(readability/streams)
#include <iomanip>
#include <map>
#include <set>
#include <sstream>
#include <utility>  // pair

#include "caffe/logging.hpp"

#define USE_OPENCV

#ifdef _MSC_VER
	#ifdef CAFFE_EXPORTS
		#define CAFFE_API __declspec(dllexport)
	#else 
		#define CAFFE_API __declspec(dllimport)
	#endif //CAFFE_EXPORTS
#else 
	#define CAFFE_API
#endif

#ifdef _MSC_VER
	#pragma waring(disable:4251)
#endif

#define STRINGFY(m) #m
#define AS_STRING(m) STRINGFY(m)

#define DISABLE_COPY_AND_ASSIGN(classname)  \
  private: 									\
  	classname(const classname&) = delete;   \
  	classname(classname &&) = delete;       \
  	classname& operator=(const classname&) = delete; \
  	classname& operator=(classname&&) = delete;

#define NOT_IMPLEMENTED LOG(FATAL) << "Not Implemented."
#define NO_GPU LOG(FATAL) << "Can not use GPU in cpu mode."

#define STUB_GPU(classname) \
template <typename Dtype> \
void classname<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom, \
    const vector<Blob<Dtype>*>& top) { NO_GPU; } \
template <typename Dtype> \
void classname<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top, \
    const vector<bool>& propagate_down, \
    const vector<Blob<Dtype>*>& bottom) { NO_GPU; } \

#define STUB_GPU_FORWARD(classname, funcname) \
template <typename Dtype> \
void classname<Dtype>::funcname##_##gpu(const vector<Blob<Dtype>*>& bottom, \
    const vector<Blob<Dtype>*>& top) { NO_GPU; } \

#define STUB_GPU_BACKWARD(classname, funcname) \
template <typename Dtype> \
void classname<Dtype>::funcname##_##gpu(const vector<Blob<Dtype>*>& top, \
    const vector<bool>& propagate_down, \
    const vector<Blob<Dtype>*>& bottom) { NO_GPU; } \
	
namespace caffe {
using std::vector;
using std::string;
using std::ostringstream;
using std::shared_ptr;	
using std::fstream;
using std::ios;
using std::isnan;
using std::isinf;
using std::iterator;
using std::make_pair;
using std::map;
using std::ostringstream;
using std::pair;
using std::set;
using std::string;
using std::stringstream;
using std::vector;
using std::shared_ptr;

}
#endif //CAFFE_BASE_HPP_